One procedure used by malicious parties to introduce malware into computer systems involves intentionally causing a stack buffer overflow. By taking advantage of an error in an existing software program, an attacker can overflow the stack buffer in such a way as to cause malicious code to be executed. By causing specific values to be written to specific locations in the overflowed stack buffer, the attacker takes over the flow of execution, and thereby runs malware on the system.
One known exploit of this type involves an attacker overwriting the Structured Exception Handling (SEH) record on the stack, so as to cause the attacker's malicious code to execute when an exception is thrown. More specifically, the Structured Exception Handling mechanism utilizes a linked list of exception structures. Each record in the linked list includes a pointer to an exception handler (for handling a specific exception type) and a pointer to the next record in the list (Next pointer). The first exception record is stored at a known location on the stack. When an exception occurs, the exception handler pointed to by the first record is called. If the exception handler can process the exception that occurred, it does so and then returns. Otherwise, it calls the next exception handler in the list.
The attacker leverages the stack buffer overflow to overwrite the pointer in the first exception record with the address of a fake exception handler. When an exception occurs, the fake exception handler is called instead of the legitimate exception handler. The fake exception handler manipulates the flow of execution so as to transfer control to the attacker's malicious shellcode. More specifically, the attacker further uses the stack buffer overflow to overwrite a specific location in the stack with the beginning of the attacker's shellcode. The fake exception handler then modifies the value of the stack pointer so as to continue execution from that location when the fake exception handler returns.
Because attacks which are based on overwriting the SEH record are common, several conventional techniques are employed to attempt to detect and prevent such attacks. In one such technique, the operating system checks that the last entry in the exception registration record chain has its Next pointer set to a special termination value (0xFFFFFFFF). Unfortunately, attackers can easily circumvent this approach by creating a fake chain of exception registration records, in which the Next pointer of the last record is set to the proper terminating value. Because the first exception record is always located at the same position on the stack, it is easy for an attacker to create a chain of fake exception records.
A similar technique is called Structured Exception Handling Overwrite Protection (SEHOP). In this approach, the operating system checks that the last entry in the chain is a specific exception handler (ntdll!FinalExceptHandler). An attacker can circumvent this technique by creating a chain of fake exception records as described above, in which the Next pointer of the next to last record points to the expected last entry.
Another approach involves placing specific random values (“cookies”) in the vicinity of vulnerable areas of the stack frame. By comparing current cookie values with control values, the operating system attempts to mitigate against stack buffer overflow exploits. This method is implemented in the Microsoft family of compilers by compiling source code with the GS flag. Attackers can circumvent this approach by avoiding cookie overwrite, or by guessing and maintaining the cookie values. Additionally, not all source code is compiled with the GS flag, and thus not all programs are protected in this manner. Even for software compiled with the GS flag, not all frames contain the cookies as a result of compiler optimization of the executable image.
Microsoft has developed a technology known as SafeSEH, which ensures that only specific routines in a protected module (DLL or EXE) are used for handling exceptions. This technique is employed by 64-bit exception handling code, and can be optionally used by 32-bit binaries. However, 32-bit code must be explicitly recompiled with a compiler supporting the SafeSEH technology. Commonly, an attacker avoids SafeSEH detection by using code from legacy modules which were compiled with an older compiler.
Another SEH validation method involves checking the memory attributes of the exception handler's address. If the handler is not in an executable section of memory (PAGE_EXECUTE_XXX), it is flagged as an exploit. This protects against some attacks, but does not catch fake exception handlers, because fake exception handlers are always located in an executable section of memory.
It would be desirable to address these issues.